import ToolBase from '@/core/tools/base'
import ImageSelection from '@/assets/images/tools/selection.svg'
import { ToolName } from '../public'
import toolSlice, { SerializableToolObject } from '@/reducers/toolSlice'
import { AppDispatch } from '@/store'
import LayerSelection from '../layers/selection'
import { renderer } from '../renderer'
import { getRelMousePosition } from '../compute/mousePosition'
import { useAppSelector } from '@/store'
import { Micon } from '@/assets/iconfont'

export default class ToolSelection extends ToolBase {
  static ToolItem: React.FC<SerializableToolObject> = (item) => {
    return <>
      <a className='tool-button'>
        <div className='tool-button-icon'>
          <Micon type='micon-selection' style={{ fontSize: 24 }}></Micon>
        </div>
        <div className='tool-button-label'>{ item.label }</div>
      </a>
    </>
  }

  static Params:  React.FC = () => {
    const toolsState = useAppSelector((state) => state.tools)
    if(!toolsState.active) return ''

    return <>
      <div className='params-field'>X：{ toolsState.active.x1 }</div>
      <div className='params-field'>Y：{ toolsState.active.y1 }</div>
      <div className='params-field'>宽：{ toolsState.active.width }</div>
      <div className='params-field'>高：{ toolsState.active.height }</div>
    </>
  }

  name: ToolName = 'selection'
  label = '选区工具'
  description = '快捷键[....]'
  layerSelection?: LayerSelection

  constructor(){
    super()
  }

  onActive(dispatch: AppDispatch){
    dispatch(toolSlice.actions.activate(this.name))

    const mouseData = {
      initX: 0,
      initY: 0,
      pressed: false,
    }

    const createSelection = (options: Partial<Pick<LayerSelection, 'x1' | 'y1' | 'x2' | 'y2' | 'animation'>> = {}) => {
      if(this.layerSelection){
        if(options.x1 !== undefined) this.layerSelection.x1 = options.x1
        if(options.y1 !== undefined) this.layerSelection.y1 = options.y1
        if(options.x2 !== undefined) this.layerSelection.x2 = options.x2
        if(options.y2 !== undefined) this.layerSelection.y2 = options.y2
        renderer.update(this.layerSelection.id, this.layerSelection, dispatch)
      }
      else {
        this.layerSelection = new LayerSelection({
          name: '新建选区',
          ctxType: 'raster',
          x1: options.x1,
          y1: options.y1,
          x2: options.x2,
          y2: options.y2,
          animation: false
        })
      }
      
      dispatch(toolSlice.actions.update(this.serialize()))
      if(!renderer.hasLayer(this.layerSelection.id)) renderer.add(this.layerSelection, dispatch)
      else renderer.update(this.layerSelection.id, this.layerSelection.serialize(), dispatch)
    }
    
    this.subscribe('mousedown', (e) => {
      if(!renderer.rasterCtx) return
      const relMousePosition = getRelMousePosition(renderer.rasterCtx.canvas, e)
      mouseData.initX = relMousePosition.left
      mouseData.initY = relMousePosition.top
      mouseData.pressed = true
    })

    this.subscribe('mousemove', (e) => {
      if(!mouseData.pressed || !renderer.rasterCtx) return
      const relMousePosition = getRelMousePosition(renderer.rasterCtx.canvas, e)
      createSelection({
        x1: mouseData.initX,
        y1: mouseData.initY,
        x2: relMousePosition.left,
        y2: relMousePosition.top,
      })
    })

    this.subscribe('mouseup', (e) => {
      if(!mouseData.pressed) return
      mouseData.pressed = false
    })
  }

  onInActive(dispatch: AppDispatch){
    this.unsubscribe()
  }

  serialize(){
    const x1 = this.layerSelection?.x1 || 0;
    const y1 = this.layerSelection?.y1 || 0;
    const x2 = this.layerSelection?.x2 || 0;
    const y2 = this.layerSelection?.y2 || 0;
    return {
      name: this.name,
      label: this.label,
      description: this.description,
      x1: x1,
      y1: y1,
      x2: x2,
      y2: y2,
      width: Math.abs(x1 - x2),
      height: Math.abs(y1 - y2),
    }
  }

}